package com.qunar.mina.app.model;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MultiSearcher;
import org.apache.lucene.search.ParallelMultiSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Searchable;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.Scorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wltea.analyzer.lucene.IKSimilarity;

import com.qunar.mina.app.config.DirectoryConfig;
import com.qunar.wireless.ugc.qcfclient.dto.QueryResult;


public class SearcherModel {
	private static final Logger logger = LoggerFactory.getLogger(DirectoryConfig.class);

	private SearcherModel() {

	}

	/**
	 * 获取高亮器
	 * 
	 * @param query
	 * @return
	 */
	public static Highlighter getHighlighter(Query query) {
		Formatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
		Scorer scorer = new QueryScorer(query);
		Highlighter highlighter = new Highlighter(formatter, scorer);
		Fragmenter fragmenter = new SimpleFragmenter(50);
		highlighter.setTextFragmenter(fragmenter);

		return highlighter;
	}


	/**
	 * 获取多域搜索器(可以在多个索引中检索需要的数据) 
	 * 多线程搜索
	 * 
	 * @param basesearcher
	 * @param incsearcher
	 * @param flag
	 * @return
	 */
	public static MultiSearcher getParallelMultiSearcher(Searchable... searcher) {
		MultiSearcher multisearcher = null;
		Searchable[] searchers = searcher;
		try {
			multisearcher = new ParallelMultiSearcher(searchers);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
		// IKAnalyzer 的相似度评估器。
		// 该类重载了DefaultSimilarity的coord方法，提高词元命中个数在相似度比较中的权重影响，即，当有多个词元得到匹配时，文档的相似度将提高。
		multisearcher.setSimilarity(new IKSimilarity());

		return multisearcher;
	}

	/**
	 * 获取查询返回结果集
	 * 
	 * @param firstResult
	 * @param maxResult
	 * @param searcher
	 * @param topDocs
	 * @return
	 */
	public static QueryResult getQueryResult(Integer firstResult, Integer maxResult, 
			Searcher searcher, TopDocs topDocs) {
		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		List<Document> docs = new ArrayList<Document>();
		int end = Math.min(firstResult + maxResult, topDocs.totalHits);
		try {
			for (int index = firstResult; index < end; index++) {
				ScoreDoc scoreDoc = scoreDocs[index];
				Document doc = searcher.doc(scoreDoc.doc);
				docs.add(doc);
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
		QueryResult qr  = new QueryResult(topDocs.totalHits, docs);
		return qr;
	}
	
	/**
	 * 释放查询对象资源
	 * @param basesearcher 基础库searcher
	 * @param incsearcher 增量库searcher
	 * @param searcher
	 */
	public static void closeSearcher(IndexSearcher searcher, MultiSearcher multisearcher) {
		if(searcher != null) {
			try {
				searcher.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		
		if(multisearcher != null) {
			try {
				multisearcher.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
	
	public static void closeSearcher(IndexSearcher searcher) {
		if(searcher != null) {
			try {
				searcher.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
}
